package com.zhouyu.mysql;

import cn.hutool.core.collection.CollUtil;
import com.zhouyu.mysql.core.DTuple;
import com.zhouyu.mysql.core.DTupleUtil;
import com.zhouyu.mysql.dict.DictTable;
import com.zhouyu.mysql.dict.SystemDict;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.FromItemVisitorAdapter;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.PlainSelect;

import java.util.List;

/**
 * 大都督周瑜（我的微信: dadudu6789）
 */
public class SqlOptimizer {

    public QEP_TAB optimize(PlainSelect plainSelect) {
        return new QEP_TAB(plainSelect);
    }

    // 里面其实有一个QEP_TAB属性，表示查询执行计划表，也就是执行计划
    static class QEP_TAB {

        private final SqlExecutor sqlExecutor = new SqlExecutor();

        private PlainSelect plainSelectStatement;

        public QEP_TAB(PlainSelect plainSelectStatement) {
            this.plainSelectStatement = plainSelectStatement;
        }

        public String exec() {

            // 判断是否join
            List<Join> joins = plainSelectStatement.getJoins();
            if (CollUtil.isNotEmpty(joins)) {
                return sqlExecutor.join(plainSelectStatement, joins);
            } else {

                // 获取表名
                final String[] tableNameArray = new String[1];
                plainSelectStatement.getFromItem().accept(new FromItemVisitorAdapter() {
                    @Override
                    public void visit(Table table) {
                        tableNameArray[0] = table.getName();
                    }
                });
                String tableName = tableNameArray[0];
                DictTable dictTable = SystemDict.getInstance().getNameTables().get(tableName);

                DTuple dTuple = DTupleUtil.convert(plainSelectStatement);

                if (!dTuple.getFields().isEmpty()) {

                    int rootPageNo = 0;
                    boolean isSecondary = false;

                    // where条件后面是id，则走主键索引，否则走a字段辅助索引
                    if ("id".equals(dTuple.getFields().get(0).getDictColumn().getName())) {
                        rootPageNo = dictTable.getPageNo();
                    } else if ("a".equals(dTuple.getFields().get(0).getDictColumn().getName())) {
                        // 这里应该要判断where条件后面的字段，看能走哪些索引，并最终选择出一个索引，我们写死
                        isSecondary = true;
                        rootPageNo = SystemDict.getInstance().getTableIdIndexes().get(dictTable.getTableId()).get(0).getPageNo();
                    }

                    return sqlExecutor.select(plainSelectStatement, false, isSecondary, rootPageNo);
                } else {
                    // 走全表扫描
                    return sqlExecutor.select(plainSelectStatement, true, false, dictTable.getPageNo());
                }
            }
        }
    }


}
